/**
 * Copyright (c) 2013 onionframework.org
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 */
package org.onionframework.faces.extension;

import java.util.Iterator;

import javax.faces.FacesException;
import javax.faces.context.ExceptionHandler;
import javax.faces.context.ExceptionHandlerWrapper;
import javax.faces.context.FacesContext;
import javax.faces.event.ExceptionQueuedEvent;
import javax.faces.event.ExceptionQueuedEventContext;

import org.apache.commons.lang3.StringUtils;
import org.onionframework.core.config.SystemConfig;
import org.onionframework.core.exception.BusinessException;
import org.onionframework.core.exception.SystemException;
import org.onionframework.faces.web.action.support.FacesMessages;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author allan
 * 
 */
public class OnionExceptionHandler extends ExceptionHandlerWrapper {

	private static final Logger logger = LoggerFactory
			.getLogger(OnionExceptionHandler.class);
	
	private final ExceptionHandler wrapped;

	public OnionExceptionHandler(ExceptionHandler wrapped) {
		this.wrapped = wrapped;
	}

	@Override
	public ExceptionHandler getWrapped() {
		return wrapped;
	}

	@Override
	public void handle() throws FacesException {
		boolean ajax = FacesContext.getCurrentInstance().getPartialViewContext().isAjaxRequest();
		if(ajax)
			handleAjaxException();
		else
			this.wrapped.handle();
	}

	/**
	 * 处理ajax请求的异常，将异常信息作为message加入到facesContext
	 */
	private void handleAjaxException() {
		for (Iterator<ExceptionQueuedEvent> i = getUnhandledExceptionQueuedEvents()
				.iterator(); i.hasNext();) {
			ExceptionQueuedEvent event = i.next();
			ExceptionQueuedEventContext context = (ExceptionQueuedEventContext) event
					.getSource();
			Throwable t = context.getException();
			FacesMessages.addErrorMessage(getMessage(t));
		}
	}
	
	public static String getMessage(Throwable e) {
		if(e instanceof BusinessException || e instanceof SystemException)
			return e.getMessage();
		
		String message = SystemConfig.Config.getString(e.getClass().getName());
		
		if (StringUtils.isNotBlank(message))
			return message;
		
		Throwable cause = e.getCause();
		
		while(cause != null){
			
			if(cause instanceof BusinessException || cause instanceof SystemException)
				return cause.getMessage();
			/*else if(cause instanceof ConstraintViolationException){
				ConstraintViolationException cvex = (ConstraintViolationException)cause;
				Set<ConstraintViolation<?>> set = cvex.getConstraintViolations();
				List<String> messages = new ArrayList<String>(set.size());
				for(ConstraintViolation<?> cv : set){
					messages.add(cv.getMessage());
				}
				return messages.toArray(new String[]{});
			}*/
			else if (StringUtils.isNotBlank(SystemConfig.Config.getString(cause.getClass().getName()))) {
				return SystemConfig.Config.getString(cause.getClass().getName());
			}
			
			cause = cause.getCause(); 
		}
	
		return "处理异常，请联系管理员或稍后再试";
	}

}
